/**
 * @Date 14-11-2013
 * Class used to get service details
 */
package com.globalblue.services;

import java.io.File;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

import com.globalblue.xml.XMLParser;

public class ServiceHandler {
	public static final String HTTP = "http";
	public static final String TCP = "net.tcp";
	public static final String NOT_APPLICABLE = "N/A";
	public static final String FILE_FOLDER_PATH="C:\\IET_DashBoard";
	public static final String BASEADDRESS="baseAddress";
	public static final String VIRTUALIP="virtualIP";
	public static final String HTTPPORT="httpPort";
	public static final String TCPPORT="tcpPort";

	/**
	 * Get all the services from the configuration files downloaded to
	 * "C:\\IET_DashBoard"
	 * 
	 * @return
	 * @throws Exception
	 */
	public List<Service> getAllServices() throws Exception {
		List<Service> services = new ArrayList<Service>();
		File folder = new File(FILE_FOLDER_PATH);

		for (final File fileEntry : folder.listFiles()) {
			if (fileEntry.isFile()) {
				String filePath = fileEntry.getAbsolutePath();
				XMLParser parser = new XMLParser();
				String[] filePathSplit = filePath.split("-");
				String serviceName = "";
				if (filePathSplit.length > 1) {
					serviceName = filePathSplit[1];
				}
				String serviceVersion = "";
				if (filePathSplit.length > 2) {
					serviceVersion = filePathSplit[2];
				}

				Service service;
				Node node = parser.getNode(filePath, "/configuration/ServerMode/Login[1]/add");
				if (node != null) {
					Element e = (Element) node;
					service = parseLoginNode(e);
					node = parser.getNode(filePath, "/configuration/ServerMode/ServerType/add");
					e = (Element) node;
					service.setServiceName(serviceName);
					service.setDbDetails(getDbDetails(filePath));
					service.setVersion(serviceVersion);
					services.add(service);
				} else {
					NodeList nodeList = parser.getNodeList(filePath, "/configuration/system.serviceModel/services[1]/service/host/baseAddresses/add");
					if (nodeList.getLength() > 0) {
						service = new Service();
						for (int i = 0; i < nodeList.getLength(); i++) {
							node = nodeList.item(i);
							Element e = (Element) node;
							String serviceAddress = e.getAttribute(BASEADDRESS);
							String[] addressDetails = serviceAddress.split("://|/|:");
							service.setServerIp(addressDetails[1]);
							if (addressDetails[0].equals(HTTP)) {
								service.setHttpPort(addressDetails[2]);
							} else if (addressDetails[0].equals(TCP)) {
								service.setTcpPort(addressDetails[2]);
							}
						}
						service.setDbDetails(getDbDetails(filePath));
						service.setServiceName(serviceName);
						service.setVersion(serviceVersion);

						services.add(service);
					}
				}
			}
		}

		return services;
	}

	/**
	 * Parse Login node in GripsMX to and assign to service properties
	 * 
	 * @param e
	 * @return
	 */
	public Service parseLoginNode(Element e) {
		Service service = new Service();
		service.setServerIp(e.getAttribute(VIRTUALIP));
		service.setHttpPort(e.getAttribute(HTTPPORT));
		service.setTcpPort(e.getAttribute(TCPPORT));
		return service;
	}

	/**
	 * Get Database details from the related XML node
	 * 
	 * @param filePath
	 * @return
	 */
	public String getDbDetails(String filePath) {
		String dbDetails = "";
		XMLParser parser = new XMLParser();
		Node node = parser.getNode(filePath, "/configuration/connectionStrings/add");
		Element e = (Element) node;
		String dbString = "";
		if (e != null) {
			dbDetails = e.getAttribute("connectionString").trim();

			dbString = getFirstMatchString(dbDetails, "Data Source=(.*?)(\\\\\\\\|\\.|,)");
			if (!dbString.equals("")) {
				dbString += "/" + getFirstMatchString(dbDetails, "Catalog=(.*?);");
			}

			else {
				dbString = getFirstMatchString(dbDetails, "Server=(.*?);");
				if (!dbString.equals("")) {
					dbString += "/" + getFirstMatchString(dbDetails, "Database=(.*?);");
				} else {
					dbString = NOT_APPLICABLE;
				}
			}
		} else {
			dbString = NOT_APPLICABLE;
		}
		return dbString;
	}

	/**
	 * Get the first matching string when original string and regex is provided
	 * 
	 * @param string
	 * @param regex
	 * @return
	 */
	public String getFirstMatchString(String string, String regex) {
		String returnString = "";
		Pattern pattern = Pattern.compile(regex);
		Matcher matcher = pattern.matcher(string);
		while (matcher.find()) {
			returnString = matcher.group(1);
		}
		return returnString;
	}

}
